package com.vpen.server.one.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;
import org.springframework.web.socket.server.standard.TomcatRequestUpgradeStrategy;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;

import javax.annotation.Resource;
import java.util.List;

/**
 * 描述
 *
 * @author 韦鹏
 * @date 2022/11/26 19:37
 */
@Configuration
@EnableWebSocketMessageBroker
public class WebsocketConfig implements WebSocketMessageBrokerConfigurer {

    @Resource
    private SocketChanelInterceptor socketChanelInterceptor;

    /**
     * 添加这个Endpoint，这样在网页中就可以通过websocket连接上服务,也就是我们配置websocket的服务地址,并且可以指定是否使用socketjs
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        /**
         * 表示定义一个前缀为 /chat 的 endPoint，并开启 sockjs 支持，
         * sockjs 可以解决浏览器对 WebSocket 的兼容性问题，
         * 客户端将通过这里配置的 URL 来建立 WebSocket 连接
         * 连接端点
         * */
        registry.addEndpoint("/chat-endpoint").setAllowedOrigins("*");
        registry.addEndpoint("/sockJs")
                .setAllowedOrigins("*")
                .setHandshakeHandler(new DefaultHandshakeHandler(new TomcatRequestUpgradeStrategy()))
                .withSockJS();
    }

    /**
     * 配置消息代理，哪种路径的消息会进行代理处理
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        /**
         * 设置消息代理前缀
         * 即如果消息的前缀是 /topic ，就会将消息转发给消息代理（broker），
         * 再由消息代理将消息广播给当前连接的客户端。
         */
        registry.enableSimpleBroker("/topic");

        /**
         * 表示配置一个或多个前缀，通过这些前缀过滤出需要被注解方法处理的消息。
         * 例如，前缀为 /app 的 destination 可以通过@MessageMapping注解的方法处理
         * 而其他 destination （例如 /topic /queue）将被直接交给 broker 处理
         * */
        registry.setApplicationDestinationPrefixes("/app");
    }

    /**
     * 配置发送与接收的消息参数，可以指定消息字节大小，缓存大小，发送超时时间
     */
    @Override
    public void configureWebSocketTransport(WebSocketTransportRegistration registry) {
        WebSocketMessageBrokerConfigurer.super.configureWebSocketTransport(registry);
    }

    /**
     * 配置客户端入站通道拦截器，用于传递从WebSocket客户端接收到的消息
     */
    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(socketChanelInterceptor);
    }

    /**
     * 配置客户端出站通道拦截器，用于向WebSocket客户端发送服务器消息
     */
    @Override
    public void configureClientOutboundChannel(ChannelRegistration registration) {
        WebSocketMessageBrokerConfigurer.super.configureClientOutboundChannel(registration);
    }

    /***
     * 添加自定义的消息转换器，spring 提供多种默认的消息转换器，返回false,
     * 不会添加消息转换器，返回true，会添加默认的消息转换器，当然也可以把自己写的消息转换器添加到转换链中
     */
    @Override
    public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
        return WebSocketMessageBrokerConfigurer.super.configureMessageConverters(messageConverters);
    }

    /**
     * 自定义控制器方法的参数类型，有兴趣可以百度google HandlerMethodArgumentResolver这个的用法
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        WebSocketMessageBrokerConfigurer.super.addArgumentResolvers(argumentResolvers);
    }

    /**
     * 自定义控制器方法返回值类型，有兴趣可以百度google HandlerMethodReturnValueHandler这个的用法
     */
    @Override
    public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
        WebSocketMessageBrokerConfigurer.super.addReturnValueHandlers(returnValueHandlers);
    }
}
